﻿using System;
using System.Collections.Generic;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using RoketSolutions.SP2010.Infrostructure.Security;
using RoketSolutions.SP2010.SecurityTrimming.SecurityTrimming.Interfaces;
using System.Linq;
using RoketSolutions.SP2010.Infrostructure.Common.Extensions;

namespace RoketSolutions.SP2010.SecurityTrimming.SecurityTrimming
{
    public class DefaultTrimmingStrategy : ITrimmingStrategy
    {
        #region / Properties /

        private IList<SPGroup> _currentUserGropus;
        protected IList<SPGroup> CurrentUserGroups
        {
            get { return _currentUserGropus ?? (_currentUserGropus = ResolveUserGroups()); }
        }

        protected SPUser CurrentUser { get; set; }

        protected TrimmingSettings Settings { get; set; }

        #endregion

        #region / Methods /

        public void Init(SPUser currentUser, TrimmingSettings settings)
        {
            Settings = settings;
            CurrentUser = currentUser;
        }

        public bool CheckWebPartAccessibility(WebPart webpart)
        {
            var setting = Settings != null ? Settings[webpart.UniqueID] : null;
            if (setting != null)
            {
                var allow = !setting.AllowAccounts.Any() || IsUserFromAccounts(setting.AllowAccounts);
                var deny = setting.DenyAccounts.Any() && IsUserFromAccounts(setting.DenyAccounts);

                return allow && !deny;
            }
            return true;
        }

        private bool IsUserFromAccounts(IEnumerable<AccountEntity> accounts)
        {
            var result = false;

            // check whether the current user is allowed account
            var userAccounts = accounts.Where(account => account.AccountType == AccountEntityType.User).ToList();
            if (userAccounts.Any(userAccount => CurrentUser.LoginName.EqualByContent(userAccount.AccountName)))
            {
                result = true;
            }

            // check whether the current user is from allowed group
            if (!result)
            {
                var accountGroups = accounts.Where(account => account.AccountType == AccountEntityType.Group).ToList();
                if (accountGroups.Any(accountGroup=>CurrentUserGroups.Any(userGroup=>userGroup.Name.EqualByContent(accountGroup.AccountName))))
                {
                    result = true;
                }
            }

            return result;
        }

        private IList<SPGroup> ResolveUserGroups()
        {
            var securityManger = new SecurityManager();
            return securityManger.GetUserGroups(CurrentUser);
        }

        #endregion

    }
}